#include "liqneedle_server.h"
#include "protocol.h"
#include "fram_flash.h"
#include "gpio_pin.h"
#include "bsp_port.h"
#include <string.h>

// FM25V10
//-----------------------------------------------------------------------------------------
// definition
#define FLASH_CS1_LOW()  pin_set(FRAM_FLASH_CS, 0)
#define FLASH_CS1_HIGH() pin_set(FRAM_FLASH_CS, 1)

#define FLASH_WREN       0x06
#define FLASH_WRDI       0x04
#define FLASH_RDSR       0x05
#define FLASH_WRSR       0x01
#define FLASH_READ       0x03
#define FLASH_FSTRD      0x0B
#define FLASH_WRITE      0x02
#define FLASH_SLEEP      0xB9
#define FLASH_RDID       0x9F
#define FLASH_SNR        0xC3
#define FLASH_DUMMY_BYTE 0x88

//-----------------------------------------------------------------------------------------
// variable definition
static uint8_t m_bRwBusy = 0;

//-----------------------------------------------------------------------------------------
// SPI 发送1字节并接收1字节
static uint8_t fram_spi_rw(uint8_t data)
{
    uint8_t rx = 0;
    HAL_SPI_TransmitReceive(FRAM_FLASH_SPI, &data, &rx, 1, 100);
    return rx;
}

// 写使能
static void fram_write_enable(void)
{
    FLASH_CS1_LOW();
    uint8_t cmd = FLASH_WREN;
    HAL_SPI_Transmit(FRAM_FLASH_SPI, &cmd, 1, 100);
    FLASH_CS1_HIGH();
}

// 写禁止
static void fram_write_disable(void)
{
    FLASH_CS1_LOW();
    uint8_t cmd = FLASH_WRDI;
    HAL_SPI_Transmit(FRAM_FLASH_SPI, &cmd, 1, 100);
    FLASH_CS1_HIGH();
}

// 参数校验（简单异或校验）
uint8_t fram_param_checksum(const uint8_t *buf, uint32_t len)
{
    if (!buf || len == 0) return 0;
    uint8_t sum = 0xAA;
    for (uint32_t i = 0; i < len; i++) {
        sum ^= buf[i];
    }
    return sum;
}

// 读数据（带参数校验）
int fram_read(uint32_t addr, uint8_t *buf, uint32_t len)
{
    if (!buf || len == 0) return -1;
    if (addr + len > 128 * 1024) return -2; // FM25V10 128K字节
    uint8_t cmd[4];
    cmd[0] = FLASH_READ;
    cmd[1] = (addr >> 16) & 0xFF;
    cmd[2] = (addr >> 8) & 0xFF;
    cmd[3] = addr & 0xFF;

    FLASH_CS1_LOW();
    HAL_SPI_Transmit(FRAM_FLASH_SPI, cmd, 4, 100);
    HAL_SPI_Receive(FRAM_FLASH_SPI, buf, len, 1000);
    FLASH_CS1_HIGH();
    return 0;
}

// 写数据（带参数校验）
int fram_write(uint32_t addr, const uint8_t *buf, uint32_t len)
{
    if (!buf || len == 0) return -1;
    if (addr + len > 128 * 1024) return -2; // FM25V10 128K字节
    uint8_t cmd[4];
    cmd[0] = FLASH_WRITE;
    cmd[1] = (addr >> 16) & 0xFF;
    cmd[2] = (addr >> 8) & 0xFF;
    cmd[3] = addr & 0xFF;

    fram_write_enable();
    FLASH_CS1_LOW();
    HAL_SPI_Transmit(FRAM_FLASH_SPI, cmd, 4, 100);
    HAL_SPI_Transmit(FRAM_FLASH_SPI, (uint8_t *)buf, len, 1000);
    FLASH_CS1_HIGH();
    fram_write_disable();
    return 0;
}

// 读写测试接口
int fram_rw_test(void)
{
    uint8_t wbuf[64], rbuf[64];
    uint32_t addr = 0x1000;
    for (uint8_t i = 0; i < sizeof(wbuf); i++) wbuf[i] = i;

    // 写入
    if (fram_write(addr, wbuf, sizeof(wbuf)) != 0)
        return -1;

    // 清空读缓冲
    memset(rbuf, 0, sizeof(rbuf));

    // 读取
    if (fram_read(addr, rbuf, sizeof(rbuf)) != 0)
        return -2;

    // 校验
    if (memcmp(wbuf, rbuf, sizeof(wbuf)) != 0)
        return -3;

    // 校验码
    uint8_t sum = fram_param_checksum(rbuf, sizeof(rbuf));
    // 可根据需要打印sum或返回
    return sum;
}